﻿/*
 				________________________________COPYRIGHT_______________________________________
				Die Veröffentlichung dieses Objektes ist Illegal und wird strafrechtlich verfolgt
				werden. Sollte es zu einer Veröffentlichung kommen werden wir die Daten des
				Herrausgebers fündig machen und Anzeige erstatten. Desweiteren ist
				auch jeglicher Besitz dieses Objektes Illegal und kann ebenfalls als Grund für
				eine Anzeige verwendet werden.
				Ausnahmen der veröffentlichung und verleihung gelten nur wenn der Grundbesitzer
				diese durchführt.
				Die Uhrheberrechte dieses Objektes liegen der Entwickler Gruppe CyberScripting vor. 
                © 2011.
 */


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using cubeworld.Blocks;
using System.Threading;

namespace cubeworld.World
{
    public class Chunk
    {
        public List<Block> Blocks = new List<Block>();
        public Block[,,] ABlocks;

        public int StartX;
        public int StartZ;
        public BoundingBox Bounds;

        public bool Visible = true;
        public bool IsChanged = false;

        public Rectangle ChunkKoordiSystem;

        public Chunk(int startX, int startZ)
        {
            this.StartX = startX;
            this.StartZ = startZ;
            ChunkKoordiSystem = new Rectangle(startX, startZ, 16, 16);
            ABlocks = new Block[16, 70, 16];


            Bounds = new BoundingBox(new Vector3(startX, -65, startZ), new Vector3(startX + 16, 9, startZ + 16));  
        }
      
        public void RenderChunk()
        {
            int i = 0;
            for (int x = 0; x < 16; x++)
            {
                for (int y = 0; y < 70; y++)
                {
                    for (int z = 0; z < 16; z++)
                    {
                        var block = ABlocks[x, y, z];

                        if (block != null)
                        {
                            Vector3 blockPosition = Data.graphicsDevice.Viewport.Project(block.Position,Data.camera.Projection, Data.camera.View, Matrix.Identity);
                            Rectangle screen = Data.graphics.GraphicsDevice.Viewport.Bounds;
                            Rectangle blockRect = new Rectangle((int) blockPosition.X, (int) blockPosition.Y,1, 1);

                            if (screen.Intersects(blockRect))
                                block.Draw();
                        }
                    }
                }
            }
        }


        public void SaveChunk()
        {
            /*string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
                "\\cubeworlds\\world\\chunk" + StartX.ToString() + StartZ.ToString();
            try
            {
                Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\cubeworlds");
                Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\cubeworlds\\world");
            }
            catch { }
            
            FileInfo FI = new FileInfo(path);
            FileStream FS = FI.Create();
            FS.Close();

            StreamWriter sw = null;
            try { sw = new StreamWriter(path); }
            catch {  }
            
            sw.WriteLine(blocks.Count);

            for (int i = 0; i < blocks.Count; i++)
            {
                sw.WriteLine(blocks[i].ID);
                sw.WriteLine(blocks[i].Position.X);
                sw.WriteLine(blocks[i].Position.Y);
                sw.WriteLine(blocks[i].Position.Z);
                if (blocks[i].visible)
                    sw.WriteLine(1);
                else
                    sw.WriteLine(0);
            }

            sw.Close();
            isChanged = false;*/
            Console.WriteLine("Couldn't save Map. Sorry!");
        }

        public void LoadChunk(bool bo = false)
        {
            StreamReader sr = null;
            try
            {
                String path = (Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
                               "\\cubeworlds\\world\\chunk" + StartX.ToString() + StartZ.ToString());
                sr = new StreamReader(path);

                int count = Convert.ToInt32(sr.ReadLine());

                for (int i = 0; i < count; i++)
                {
                    Block b = createBlockFromID(Convert.ToInt32(sr.ReadLine()), Convert.ToInt32(sr.ReadLine()),
                        Convert.ToInt32(sr.ReadLine()), Convert.ToInt32(sr.ReadLine()));
                    if (Convert.ToInt32(sr.ReadLine()) == 0)
                        b.visible = false;
                    else
                        b.visible = true;
                    ABlocks[Convert.ToInt32(b.Position.X), Convert.ToInt32(b.Position.Y), Convert.ToInt32(b.Position.Z)] = b;
  
                }

                sr.Close();
            }

            catch
            {
                try
                {
                    sr.Close();
                }
                catch { }
                if (bo)
                {
                    Console.WriteLine("Generate Chunk...");
                    this.GenerateChunk();
                }
                else
                {
                    Thread newThread;
                    newThread = new Thread(new ThreadStart(this.GenerateChunk));
                    newThread.Start();
                }
            }

            

        }

        public void GenerateChunk()
        {
            ChunkGenerator chunGen = new ChunkGenerator(BiomList.biom[0], StartX, StartZ);
            ABlocks = chunGen.Generate(16);
        }


        public bool isVisible()
        {
            BoundingFrustum fr = new BoundingFrustum(Data.camera.View * Data.camera.Projection);

            //return fr.Intersects(bounds); 
            return true;
        }

        private Block createBlockFromID(int id, float x, float y, float z)
        {
            Block block;
            if (id == 1)
            {
                block = new MarsRock(new Vector3(x, y, z));
            }
            else if (id == 2)
            {
                block = new Stone(new Vector3(x, y, z));
            }
            else if (id == 3)
            {
                block = new LavaStone(new Vector3(x, y, z));
            }
            else if (id == 4)
            {
                block = new BrimStone(new Vector3(x, y, z));
            }
            else
            {
                throw new Exception("Unknow Block ID in Biom");
            }
            return block;
        }
    }
}
